
package com.bleeth.fx.font;

import cn.hutool.core.collection.CollUtil;
import javafx.css.*;
import javafx.scene.paint.Color;
import javafx.scene.paint.Paint;
import javafx.scene.text.Font;
import javafx.scene.text.FontSmoothingType;
import javafx.scene.text.Text;

import java.util.List;

public class MFontIcon extends Text {


    private static final StyleablePropertyFactory<MFontIcon> FACTORY = new StyleablePropertyFactory<>(Text.getClassCssMetaData());
    private final String STYLE_CLASS = "-fx-font-icon";
    private static final double DEFAULT_SIZE = 16;

    public MFontIcon() {
        initialize();
    }

    public MFontIcon(String code) {
        this(code, DEFAULT_SIZE);
    }

    public MFontIcon(String code, Color color) {
        this(code, DEFAULT_SIZE, color);
    }

    public MFontIcon(String code, double size) {
        this(code, size, Color.rgb(117, 117, 117));
    }

    public MFontIcon(String code, double size, Color color) {
        initialize();
        setDescription(code);
        setSize(size);
        setColor(color);

        setText(String.valueOf(IconFontLoader.getCode(code)));
    }


    private void initialize() {
        getStyleClass().add(STYLE_CLASS);
        setFont(IconFontLoader.font);
        setFontSmoothingType(FontSmoothingType.GRAY);

        sizeProperty().addListener((observable, oldValue, newValue) -> {
            Font font = getFont();
            setFont(Font.font(IconFontLoader.font.getFamily(), newValue.doubleValue()));
        });

        colorProperty().addListener((observable, oldValue, newValue) -> setFill(newValue));

        contentProperty().addListener((observable, oldValue, newValue) -> {
            if (newValue != null) {
                setText(String.valueOf(IconFontLoader.getCode(newValue)));
            }
        });
    }


    public static MFontIcon getRandomIcon(double size, Color color) {
        String key = IconFontLoader.getRandomKey();
        return new MFontIcon(key, size, color);
    }


    private final StyleableStringProperty content = new SimpleStyleableStringProperty(
            StyleableProperties.CONTENT,
            this,
            "content"
    );

    private final StyleableDoubleProperty size = new SimpleStyleableDoubleProperty(
            StyleableProperties.SIZE,
            this,
            "size",
            DEFAULT_SIZE
    );

    private final StyleableObjectProperty<Paint> color = new SimpleStyleableObjectProperty<>(
            StyleableProperties.COLOR,
            this,
            "color",
            Color.rgb(117, 117, 117)
    );

    public String getContent() {
        return content.get();
    }

    /**
     * Specifies the icon's code.
     */
    public StyleableStringProperty contentProperty() {
        return content;
    }

    public void setDescription(String code) {
        this.content.set(code);
    }

    public double getSize() {
        return size.get();
    }

    /**
     * Specifies the size of the icon.
     */
    public StyleableDoubleProperty sizeProperty() {
        return size;
    }

    public void setSize(double size) {
        this.size.set(size);
    }

    public Paint getColor() {
        return color.get();
    }


    public StyleableObjectProperty<Paint> colorProperty() {
        return color;
    }

    public void setColor(Paint color) {
        this.color.set(color);
    }


    public static class StyleableProperties {
        private static final List<CssMetaData<? extends Styleable, ?>> cssMetaDataList;

        private static final CssMetaData<MFontIcon, String> CONTENT =
                FACTORY.createStringCssMetaData(
                        "-fx-icon-code",
                        MFontIcon::contentProperty
                );

        private static final CssMetaData<MFontIcon, Number> SIZE =
                FACTORY.createSizeCssMetaData(
                        "-fx-size",
                        MFontIcon::sizeProperty,
                        DEFAULT_SIZE
                );

        private static final CssMetaData<MFontIcon, Paint> COLOR =
                FACTORY.createPaintCssMetaData(
                        "-fx-color",
                        MFontIcon::colorProperty,
                        Color.rgb(117, 117, 117)
                );

        static {
            cssMetaDataList = CollUtil.newArrayList(CONTENT, SIZE, COLOR);
        }
    }

    public static List<CssMetaData<? extends Styleable, ?>> getClassCssMetaDataList() {
        return StyleableProperties.cssMetaDataList;
    }


    @Override
    public List<CssMetaData<? extends Styleable, ?>> getCssMetaData() {
        return MFontIcon.getClassCssMetaDataList();
    }
}
